package cn.virens.service.impl.platform.generator;

import java.io.OutputStream;
import java.util.Map;
import java.util.Properties;

import org.beetl.core.Configuration;
import org.beetl.core.GroupTemplate;
import org.beetl.core.ResourceLoader;
import org.beetl.core.Template;
import org.beetl.core.resource.ClasspathResourceLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import cn.hutool.core.io.FileUtil;
import cn.virens.common.CloseableUtil;
import cn.virens.service.impl.platform.generator.common.TableFileUtil;
import cn.virens.service.impl.platform.generator.common.TableInfo;
import cn.virens.service.impl.platform.generator.common.TableInfoEx;

@Service
public class GeneratorDatabaseTemplate implements InitializingBean {
	protected final Logger logger = LoggerFactory.getLogger(GeneratorDatabaseTemplate.class);

	/** 保存地址 */
	@Value("${generator.db.path.java}")
	private String pathJava;

	@Value("${generator.db.path.html}")
	private String pathHtml;

	/** view页面的模版路径 */
	@Value("${generator.db.tpl.view}")
	private String tplView;

	/** list页面的模版路径 */
	@Value("${generator.db.tpl.index}")
	private String tplIndex;

	/** add页面的模版路径 */
	@Value("${generator.db.tpl.create}")
	private String tplCreate;

	/** edit页面的模版路径 */
	@Value("${generator.db.tpl.update}")
	private String tplUpdate;

	/** 控制器的模版路径 */
	@Value("${generator.db.tpl.control}")
	private String tplControl;

	/** 服务接口的模版路径 */
	@Value("${generator.db.tpl.service}")
	private String tplService;

	/** 服务实现的模版路径 */
	@Value("${generator.db.tpl.serviceimpl}")
	private String tplServiceImpl;

	/** 基础包路径 */
	@Value("${generator.db.package.base}")
	private String packageBase;

	/** 数据model包路径 */
	@Value("${generator.db.package.model}")
	private String packageModel;

	/** 数据库mapper包路径 */
	@Value("${generator.db.package.mapper}")
	private String packageMapper;

	/** 控制器包路径 */
	@Value("${generator.db.package.control}")
	private String packageControl;

	/** 服务接口包路径 */
	@Value("${generator.db.package.service}")
	private String packageService;

	/** 服务实现包路径 */
	@Value("${generator.db.package.serviceimpl}")
	private String packageServiceImpl;

	private GroupTemplate template;
	private Configuration configuration;
	private ResourceLoader resourceLoader;

	/**
	 * 构建表信息
	 * 
	 * @return 已经添加了基础信息的表信息对象
	 */
	public TableInfoEx info() {
		TableInfoEx info = new TableInfoEx();
		info.setPackageServiceImpl(packageServiceImpl);
		info.setPackageService(packageService);
		info.setPackageControl(packageControl);
		info.setPackageMapper(packageMapper);
		info.setPackageModel(packageModel);
		info.setPackageBase(packageBase);

		return info;
	}

	/**
	 * 生成控制器
	 * 
	 * @param info 表信息
	 * @param map  额外信息
	 */
	public String renderControl(TableInfoEx info, Map<String, Object> map) {
		return render(TableFileUtil.controlFile(pathJava, info), tplControl, info, map);
	}

	/**
	 * 生成服务接口
	 * 
	 * @param info 表信息
	 * @param map  额外信息
	 */
	public String renderService(TableInfoEx info, Map<String, Object> map) {
		return render(TableFileUtil.serviceFile(pathJava, info), tplService, info, map);
	}

	/**
	 * 生成服务实现
	 * 
	 * @param info 表信息
	 * @param map  额外信息
	 */
	public String renderServiceImpl(TableInfoEx info, Map<String, Object> map) {
		return render(TableFileUtil.serviceImplFile(pathJava, info), tplServiceImpl, info, map);
	}

	/**
	 * 生成View页面
	 * 
	 * @param info 表信息
	 * @param map  额外信息
	 */
	public String renderPageView(TableInfoEx info, Map<String, Object> map) {
		return render(TableFileUtil.pageFile(pathHtml, info, "view"), tplView, info, map);
	}

	/**
	 * 生成Index页面
	 * 
	 * @param info 表信息
	 * @param map  额外信息
	 */
	public String renderPageIndex(TableInfoEx info, Map<String, Object> map) {
		return render(TableFileUtil.pageFile(pathHtml, info, "index"), tplIndex, info, map);
	}

	/**
	 * 生成Add页面
	 * 
	 * @param info 表信息
	 * @param map  额外信息
	 */
	public String renderPageCreate(TableInfoEx info, Map<String, Object> map) {
		return render(TableFileUtil.pageFile(pathHtml, info, "create"), tplCreate, info, map);
	}

	/**
	 * 生成Edit页面
	 * 
	 * @param info 表信息
	 * @param map  额外信息
	 */
	public String renderPageUpdate(TableInfoEx info, Map<String, Object> map) {
		return render(TableFileUtil.pageFile(pathHtml, info, "update"), tplUpdate, info, map);
	}

	private String render(String path, String tpl, TableInfo info, Map<String, Object> map) {
		OutputStream stream = null;

		try {
			// 获取输出文件流
			stream = FileUtil.getOutputStream(path);

			// 获取模版 & 绑定参数
			Template templ = template.getTemplate(tpl);
			templ.binding("info", info);
			templ.binding(map);

			// 渲染内容
			templ.renderTo(stream);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		} finally {
			CloseableUtil.close(stream);
		}

		return path;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		Properties properties = new Properties();
		properties.put("DELIMITER_PLACEHOLDER_START", "${{");
		properties.put("DELIMITER_PLACEHOLDER_END", "}}");

		this.configuration = new Configuration(properties);
		this.resourceLoader = new ClasspathResourceLoader();
		this.template = new GroupTemplate(resourceLoader, configuration);
	}
}
